package com.linkoog.devtools.code_generator.wizard.generate.database.table.panel;

import com.linkoog.devtools.code_generator.ActionCallback;
import com.linkoog.devtools.code_generator.CodeGenIcons;
import com.linkoog.devtools.code_generator.database.dao.DatabaseDao;
import com.linkoog.devtools.code_generator.database.domain.ConnectionInfo;
import com.linkoog.devtools.code_generator.database.domain.DatabaseInfo;
import com.linkoog.devtools.code_generator.wizard.generate.database.table.dialog.datasource.DataSourceSettingDialog;
import com.linkoog.devtools.code_generator.wizard.generate.database.table.dialog.datasource.panel.DatabaseComboBoxCellRender;
import com.linkoog.devtools.code_generator.wizard.generate.database.table.model.datasource.ConnectionInfoItem;
import com.linkoog.devtools.code_generator.wizard.generate.database.table.model.datasource.DatasourceComboBoxCellRender;
import com.linkoog.devtools.code_generator.wizard.generate.database.table.model.datasource.DatasourceOperationItem;
import com.linkoog.devtools.code_generator.setting.persistent.CodeGenDevToolsPersistent;
import com.linkoog.devtools.code_generator.util.StringUtil;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.PopupMenuListenerAdapter;
import com.intellij.ui.components.JBLoadingPanel;

import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.PopupMenuEvent;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

public class DatasourceInfoContextPanel implements Disposable {


    private JPanel myMainPanel;
    private JComboBox connectionComboBox;
    private JComboBox databaseComboBox;
    private JComboBox schemaComboBox;

    private JButton showTablesButton;
    private JPanel contextPanel;

    private Consumer<ConnectionInfoItem> showTableConsumer;

    private ActionCallback resetDatasourceCallback;

    private final JBLoadingPanel loadingPanel;

    public DatasourceInfoContextPanel(JBLoadingPanel loadingPanel) {
        this.loadingPanel = loadingPanel;
        //loadingPanel.add(myMainPanel, BorderLayout.CENTER);

        //databaseComboBox.setEnabled (false);
        //schemaComboBox.setEnabled (false);

        this.contextPanel.setBorder(new LineBorder(Color.LIGHT_GRAY));
        //this.contextPanel.setBorder(new TitledBorder(new LineBorder(Color.LIGHT_GRAY), "模板设置"));

        databaseComboBox.setEditable(false);
        schemaComboBox.setEditable(false);

        initDatasourceComboBox();
        initShowTablesButton();
    }

    @Override
    public void dispose() {

    }

    public Consumer<ConnectionInfoItem> getShowTableConsumer() {
        return showTableConsumer;
    }

    public void setShowTableConsumer(Consumer<ConnectionInfoItem> showTableConsumer) {
        this.showTableConsumer = showTableConsumer;
    }

    public ActionCallback getResetDatasourceCallback() {
        return resetDatasourceCallback;
    }

    public void setResetDatasourceCallback(ActionCallback resetDatasourceCallback) {
        this.resetDatasourceCallback = resetDatasourceCallback;
    }

    private void initShowTablesButton() {
        showTablesButton.setEnabled(false);

        showTablesButton.addActionListener(e -> {
            ConnectionInfoItem datasourceInfoItem = validDatasource();
            resetTableList(datasourceInfoItem);
        });
    }

    private ConnectionInfoItem validDatasource() {
        ConnectionInfoItem datasourceInfoItem = getSelectedConnectionInfo();
        if (datasourceInfoItem == null) {
            Messages.showErrorDialog(myMainPanel, "请先选择数据源！", "数据源");
            return null;
        }

        DatabaseInfo databaseInfo = getSelectedDatabaseInfo();
        if (databaseInfo == null) {
            Messages.showErrorDialog(myMainPanel, "请先选择数据库！", "数据源");
            return null;
        }

        String schema = (String) schemaComboBox.getSelectedItem();
        if (StringUtil.isBlank(schema)) {
            Messages.showErrorDialog(myMainPanel, "请先选择schema！", "数据源");
            return null;
        }

        datasourceInfoItem.setCurrentDatabase(databaseInfo.databaseName);
        datasourceInfoItem.setCurrentSchema(schema);
        return datasourceInfoItem;
    }

    private void resetTableList(ConnectionInfoItem datasourceInfoItem) {
        if (datasourceInfoItem != null && showTableConsumer != null) {
            showTableConsumer.accept(datasourceInfoItem);
        }
    }

    private ConnectionInfoItem getSelectedConnectionInfo(){
        Object selectedItemObject = connectionComboBox.getSelectedItem();
        if (selectedItemObject instanceof ConnectionInfoItem){
            return (ConnectionInfoItem) selectedItemObject;
        }
        return null;
    }

    private DatabaseInfo getSelectedDatabaseInfo(){
        Object selectedItemObject = databaseComboBox.getSelectedItem();
        if (selectedItemObject instanceof DatabaseInfo){
            return (DatabaseInfo) selectedItemObject;
        }
        return null;
    }

    private void initDatasourceComboBox() {
        connectionComboBox.setRenderer(new DatasourceComboBoxCellRender());
        resetConnectionComboBox(null);

        databaseComboBox.setRenderer(new DatabaseComboBoxCellRender());
        databaseComboBox.addItemListener(event -> {
            if (event.getStateChange() == ItemEvent.SELECTED) {
                ConnectionInfoItem infoItem = getSelectedConnectionInfo();
                if (infoItem != null){
                    Object selected = event.getItem();
                    if (selected instanceof DatabaseInfo) {
                        DatabaseInfo databaseInfo = (DatabaseInfo) selected;
                        resetSchemaComboBox(databaseInfo.schemaList, infoItem.getConnectionInfo().getSchema());
                        if (!databaseInfo.defaultFlag ){
                            infoItem.setCurrentDatabase(databaseInfo.databaseName);
                            resetTableList(infoItem);
                        }
                    }
                }
            }
        });

        connectionComboBox.addPopupMenuListener(new PopupMenuListenerAdapter() {
            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {

            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                if (e.getSource() instanceof JComboBox) {
                    JComboBox jComboBox = (JComboBox) e.getSource();
                    int index = jComboBox.getSelectedIndex();
                    Object selectedItemObject = jComboBox.getSelectedItem();
                    for (int i = 0; i < jComboBox.getItemCount(); i++) {
                        Object itemObject = jComboBox.getItemAt(i);
                        if (index != i && itemObject instanceof ConnectionInfoItem) {
                            ConnectionInfoItem itemData = (ConnectionInfoItem) itemObject;
                            itemData.setHasConnection(null);
                        }
                    }

                    if (selectedItemObject instanceof DatasourceOperationItem) {
                        showTablesButton.setEnabled(false);

                        DatasourceOperationItem operationItem = (DatasourceOperationItem) selectedItemObject;
                        //jComboBox.setSelectedIndex(0);
                        resetDatabaseComboBox(null, null);

                        if (resetDatasourceCallback != null) {
                            resetDatasourceCallback.callback();
                        }

                        SwingUtilities.invokeLater(() -> {
                            DataSourceSettingDialog dialog = new DataSourceSettingDialog(myMainPanel, () -> {
                                resetConnectionComboBox(null);
                            });
                            if (!dialog.showAndGet()) {
                                return;
                            }
                        });
                    } else if (selectedItemObject instanceof ConnectionInfoItem) {
                        ConnectionInfoItem infoItem = (ConnectionInfoItem) selectedItemObject;
                        resetDatabaseComboBox(null, infoItem);

                        AtomicBoolean switchFlag = new AtomicBoolean(false);
                        ConnectionInfoItem datasourceInfoItem = validDatasource();
                        if (datasourceInfoItem != null) {
                            loadingPanel.setLoadingText("Connection Database!");
                            loadingPanel.startLoading();

                            ApplicationManager.getApplication().executeOnPooledThread(() -> {
                                connectionComboBox.setEnabled(false);
                                try {
                                    DatabaseDao databaseDao = infoItem.getDatabaseDao();
                                    boolean test = databaseDao.validConnection();
                                    if (test) {
                                        showTablesButton.setEnabled(true);
                                        //resetTableList(datasourceInfoItem);
                                        datasourceInfoItem.setHasConnection(true);

                                        List<DatabaseInfo> databaseInfoList = databaseDao.getDatabaseInfoList();
                                        resetDatabaseComboBox(databaseInfoList, infoItem);
                                        switchFlag.set(false);
                                        /*SwingUtilities.invokeLater(() -> {
                                            Messages.showInfoMessage(myMainPanel, "连接成功", "");

                                        });*/
                                    } else {
                                        datasourceInfoItem.setHasConnection(false);
                                        SwingUtilities.invokeLater(() -> {
                                            Messages.showErrorDialog(myMainPanel, "连接失败");
                                        });
                                    }
                                } catch (Exception ex) {
                                    ex.printStackTrace();
                                    datasourceInfoItem.setHasConnection(false);
                                    SwingUtilities.invokeLater(() -> {
                                        Messages.showErrorDialog(myMainPanel, ex.getMessage());
                                    });
                                } finally {
                                    loadingPanel.stopLoading();
                                    connectionComboBox.setEnabled(true);
                                }
                            });
                        }



                        ApplicationManager.getApplication().executeOnPooledThread(() -> {

                        });
                    }
                }
            }
        });
    }

    public String validate() {
        Object selectedItemObject = connectionComboBox.getSelectedItem();
        if (!(selectedItemObject instanceof ConnectionInfoItem)) {
            return "请先选择数据源！";
        }

        DatabaseInfo databaseInfo = getSelectedDatabaseInfo();
        if (databaseInfo == null) {
            return "请先选择数据库！";
        }

        String schema = (String) schemaComboBox.getSelectedItem();
        if (StringUtil.isBlank(schema)) {
            return "请先选择schema！";
        }

        return null;
    }

    private void resetConnectionComboBox(ConnectionInfoItem infoItem) {
        connectionComboBox.removeAllItems();
        //datasourceComboBox.addItem("");
        connectionComboBox.addItem(new DatasourceOperationItem(CodeGenIcons.empty, "配置数据源"));
        List<ConnectionInfo> conns = CodeGenDevToolsPersistent.getInstance().getConnectionInfoList();
        for (ConnectionInfo conn : conns) {
            ConnectionInfoItem datasourceInfoItem = new ConnectionInfoItem(conn);
            connectionComboBox.addItem(datasourceInfoItem);
            if (infoItem != null && conn.equals(infoItem.getConnectionInfo())) {
                connectionComboBox.setSelectedItem(datasourceInfoItem);
            }
        }
    }

    private void resetDatabaseComboBox(List<DatabaseInfo> databaseInfoList, ConnectionInfoItem infoItem) {
        databaseComboBox.removeAllItems();
        if (databaseInfoList == null || databaseInfoList.isEmpty()){
            if (infoItem == null) {
                databaseComboBox.addItem("");
                resetSchemaComboBox(null, null);
            } else {
                databaseComboBox.addItem(createDatabaseInfo(infoItem));
                resetSchemaComboBox(null, infoItem.getConnectionInfo().getSchema());
            }

        }else {
            for (DatabaseInfo databaseInfo : databaseInfoList) {
                databaseComboBox.addItem(databaseInfo);
            }

            DatabaseInfo defaultDatabaseInfo = findDatabaseInfo(databaseInfoList, infoItem.getConnectionInfo().getDatabase());
            if (infoItem == null) {
                defaultDatabaseInfo = databaseInfoList.get(0);
            }

            if (defaultDatabaseInfo != null){
                databaseComboBox.setSelectedItem(defaultDatabaseInfo);
            }

            resetSchemaComboBox(defaultDatabaseInfo.schemaList, infoItem.getConnectionInfo().getSchema());
        }
    }

    private DatabaseInfo findDatabaseInfo(List<DatabaseInfo> databaseInfoList, String database){
        for (DatabaseInfo databaseInfo : databaseInfoList) {
            if (databaseInfo.databaseName != null && databaseInfo.databaseName.equals(database)){
                return databaseInfo;
            }
        }
        return null;
    }

    private DatabaseInfo createDatabaseInfo(ConnectionInfoItem infoItem){
        DatabaseInfo databaseInfo = new DatabaseInfo();
        databaseInfo.databaseName = infoItem.getConnectionInfo().getDatabase();
        databaseInfo.schemaList = Arrays.asList(infoItem.getConnectionInfo().getSchema());
        databaseInfo.defaultFlag = true;
        return databaseInfo;
    }


    private void resetSchemaComboBox(List<String> schemaList, String defaultShema) {
        schemaComboBox.removeAllItems();
        if (schemaList == null || schemaList.isEmpty()){
            if (StringUtil.isBlank(defaultShema)) {
                schemaComboBox.addItem("");
            } else {
                schemaComboBox.addItem(defaultShema);
            }
        }else {
            String defaultshema = schemaList.get(0);
            for (String shema : schemaList) {
                schemaComboBox.addItem(shema);
                if (shema != null && shema.equals(defaultShema) ){
                    defaultshema = shema;
                }
            }

            schemaComboBox.setSelectedItem(defaultshema);
        }
    }


    public JPanel getMyMainPanel() {
        return myMainPanel;
    }





}
